#version 100

// 结构体定义
struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};

struct Light {
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

// 使用 varying 关键字声明输入变量
varying vec3 vertexColor;
varying vec3 Norm;
varying vec3 FragPos;

// 没有 out 关键字，使用 gl_FragColor 输出颜色
// 这里不重复定义 objectColor，因为后面会用到传入的 uniform

uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform Material material;
uniform Light light;

void main()
{
    // 默认物体颜色为白色
    vec3 objectColor = vec3(1.0, 1.0, 1.0); // 白色

    // 环境光照
    vec3 ambient = light.ambient * material.ambient * vertexColor;

    // 漫反射光照
    vec3 norm = normalize(Norm); // 归一化法向量
    vec3 lightDir = normalize(light.position - FragPos); // 光源方向
    float diff = max(dot(norm, lightDir), 0.0); // 漫反射系数
    vec3 diffuse = light.diffuse * (diff * material.diffuse) * vertexColor;

    // 镜面反射光照
    vec3 viewDir = normalize(viewPos - FragPos); // 视线方向
    vec3 reflectDir = reflect(-lightDir, norm); // 反射方向
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); // 镜面反射系数
    vec3 specular = light.specular * (spec * material.specular) * vertexColor;

    // 最终颜色 = 环境光 + 漫反射 + 镜面反射
    vec3 result = ambient + diffuse + specular;

    // 将颜色转换为灰度值
    float gray = dot(result, vec3(0.299, 0.587, 0.114)); // 使用常见的灰度转换公式

    // 根据片段的世界坐标的 -Y 方向调整灰度值
    float yPos = -FragPos.y; // 获取片段的世界坐标的 Y 分量并取反
    float adjustedGray = (yPos + 1.0) * 0.5 * 50.0; // 压缩动态范围

    // 使用法向量的变化增强轮廓
    float edgeFactor = 1.0 - dot(norm, normalize(viewDir)); // 计算轮廓因子
    adjustedGray *= (1.0 + edgeFactor * 0.5); // 增强轮廓

    // Gamma 校正
    float gamma = 2.2; // Gamma 值
    vec3 grayColor = vec3(adjustedGray / 255.0);
    grayColor = pow(grayColor, vec3(1.0 / gamma)); // Gamma 校正

    // 输出灰度颜色
    gl_FragColor = vec4(grayColor, 1.0);
}
